package dao

import (
	"errors"
	"fmt"
	"github.com/go-pdf/fpdf"
	"go.uber.org/zap"
	"log"
	"order_srv/model"
	"order_srv/order"
	"order_srv/orderclient"
	"os"
	"path/filepath"
	"smart-health-platforms/pkg"
	"time"
	model2 "user_srv/model"
)

// 添加发票
func InvoiceCreate(in *order.InvoiceCreateRequest) (*model.Invoice, error) {
	//接收订单参数
	orders := model.Order{
		OrderSn: in.OrderSn,
	}
	//接收用户参数
	user := model2.Users{
		Id: uint(in.UserId),
	}
	//查询订单是否存在
	if err := orders.GetByOrderOrderNo(); err != nil {
		pkg.Error("订单查询失败", zap.Error(err))
		return nil, errors.New("订单查询失败")
	}
	log.Println(orders)
	if orders.PayStatus != 2 {
		pkg.Info("订单未支付", zap.String("orderSn", in.OrderSn))
		return nil, errors.New("订单未支付")
	}
	//判断是否是用户自己的订单
	if orders.UserId != uint32(in.UserId) {
		pkg.Info("不是用户自己的订单", zap.String("orderSn", in.OrderSn))
		return nil, errors.New("不是用户自己的订单")
	}
	//查看用户信息
	if err := user.GetUserInfoById(int(in.UserId)); err != nil {
		pkg.Error("用户查询失败", zap.Error(err))
		return nil, errors.New("用户查询失败")
	}
	//添加发票
	invoice := &model.Invoice{
		OrderSn:  in.OrderSn,
		UserId:   uint32(in.UserId),
		ComTitle: in.ComTitle,
		Amount:   orders.TotalPrice,
		Title:    user.NickName,
	}
	if err := invoice.Create(); err != nil {
		pkg.Error("发票添加失败", zap.Error(err))
		return nil, errors.New("发票添加失败")
	}
	return invoice, nil
}

// 未审核发票列表
func InvoiceList(in *order.InvoiceListRequest) ([]*orderclient.InvoiceList, error) {
	//查询发票列表
	var invoice model.Invoice
	invoiceList, err := invoice.GetUnReviewList()
	if err != nil {
		pkg.Error("发票查询失败", zap.Error(err))
		return nil, errors.New("发票查询失败")
	}

	//转换为proto格式
	var invoiceLists []*orderclient.InvoiceList
	for _, v := range invoiceList {
		list := orderclient.InvoiceList{
			InvoiceId:    int64(v.Id),
			OrderSn:      v.OrderSn,
			UserId:       int64(v.UserId),
			Amount:       float32(v.Amount),
			Status:       int64(v.Status),
			Title:        v.Title,
			CreateTime:   v.CreatedAt.Format("2006-01-02 15:04:05"),
			ReviewerId:   int64(v.ReviewerId),
			ReviewerTime: v.ReviewerTime.Format("2006-01-02 15:04:05"),
			ReviewerSeal: v.ReviewerSeal,
			ReviewerNote: v.ReviewerNote,
		}
		invoiceLists = append(invoiceLists, &list)
	}
	return invoiceLists, nil
}

// 发票审核
func InvoiceReview(in *order.InvoiceReviewRequest) (*model.Invoice, error) {
	//接收发票参数
	invoice := model.Invoice{
		OrderSn: in.OrderSn,
	}
	//接收用户参数
	user := model2.Users{
		Id: uint(in.ReviewerId),
	}
	//查询发票状态是否是待审核
	if err := invoice.Review(); err != nil {
		pkg.Error("发票查询失败", zap.Error(err))
		return nil, errors.New("发票查询失败")
	}
	if invoice.Status != 0 {
		pkg.Info("发票已审核", zap.String("orderSn", in.OrderSn))
		return nil, errors.New("发票已审核")
	}
	//查询用户是否有权限
	if err := user.GetUserInfoById(int(in.ReviewerId)); err != nil {
		pkg.Error("用户查询失败", zap.Error(err))
		return nil, errors.New("用户查询失败")
	}
	//判断用户是否是管理员
	if user.UsersStatus != 2 {
		pkg.Info("用户无权审核", zap.String("orderSn", in.OrderSn))
		return nil, errors.New("用户无权审核")
	}
	//更新发票状态
	invoice.Status = int32(in.Status)
	invoice.ReviewerId = uint32(in.ReviewerId)
	invoice.ReviewerTime = time.Now()
	invoice.ReviewerSeal = in.ReviewerSeal
	invoice.ReviewerNote = in.ReviewerNote
	if err := invoice.UpdateStatus(); err != nil {
		pkg.Error("发票更新失败", zap.Error(err))
		return nil, errors.New("发票更新失败")
	}
	return &invoice, nil
}

// 全部发票列表
func Invoice(in *order.InvoiceRequest) ([]*orderclient.InvoiceList, error) {
	//查询发票列表
	var invoice model.Invoice
	invoiceList, err := invoice.ReviewList()
	if err != nil {
		pkg.Error("发票查询失败", zap.Error(err))
		return nil, errors.New("发票查询失败")
	}

	//转换为proto格式
	var invoiceLists []*orderclient.InvoiceList
	for _, v := range invoiceList {
		list := orderclient.InvoiceList{
			InvoiceId:    int64(v.Id),
			OrderSn:      v.OrderSn,
			UserId:       int64(v.UserId),
			Amount:       float32(v.Amount),
			Status:       int64(v.Status),
			Title:        v.Title,
			CreateTime:   v.CreatedAt.Format("2006-01-02 15:04:05"),
			ReviewerId:   int64(v.ReviewerId),
			ReviewerTime: v.ReviewerTime.Format("2006-01-02 15:04:05"),
			ReviewerSeal: v.ReviewerSeal,
			ReviewerNote: v.ReviewerNote,
		}
		invoiceLists = append(invoiceLists, &list)
	}
	return invoiceLists, nil
}

// 发票生成
func InvoicePDF(in *order.InvoicePDFRequest) (string, error) {
	//查询发票信息
	var invoice model.Invoice
	if err := invoice.ReviewDetail(int(in.InvoiceId)); err != nil {
		pkg.Error("查询发票信息失败", zap.Error(err), zap.Int("invoice_id", int(in.InvoiceId)))
		return "", fmt.Errorf("查询发票信息失败: %v", err)
	}

	if invoice.Id == 0 {
		pkg.Info("当前发票不存在", zap.Int("invoice_id", int(in.InvoiceId)))
		return "", errors.New("当前发票不存在")
	}

	//生成pdf文件
	filename, err := CreatePDFFile(&invoice)
	if err != nil {
		pkg.Error("生成PDF文件失败",
			zap.Error(err),
			zap.Int("invoice_id", int(invoice.Id)),
			zap.String("order_sn", invoice.OrderSn))
		return "", fmt.Errorf("生成PDF文件失败: %v", err)
	}

	pkg.Info("发票生成成功",
		zap.String("filename", filename),
		zap.Int("invoice_id", int(invoice.Id)))

	return filename, nil
}

func CreatePDFFile(invoice *model.Invoice) (string, error) {
	// 创建发票保存目录
	invoiceDir := "invoices"
	if err := os.MkdirAll(invoiceDir, 0755); err != nil {
		return "", fmt.Errorf("创建目录失败: %v", err)
	}

	pdf := fpdf.New("P", "mm", "A4", "")
	pdf.SetAutoPageBreak(true, 10)

	// 直接使用Arial字体，确保不会乱码
	pdf.SetFont("Arial", "", 12)

	pdf.AddPage()

	// 发票标题 - 使用英文
	pdf.SetFont("Arial", "B", 16)
	pdf.Cell(0, 20, "Electronic Invoice")
	pdf.Ln(25)

	// 发票基本信息 - 全部使用英文
	pdf.SetFont("Arial", "", 12)
	pdf.Cell(40, 10, fmt.Sprintf("Invoice ID: %d", invoice.Id))
	pdf.Ln(8)
	pdf.Cell(40, 10, fmt.Sprintf("Invoice Number: %s", invoice.OrderSn))
	pdf.Ln(8)
	pdf.Cell(40, 10, fmt.Sprintf("Issue Date: %s", invoice.CreatedAt.Format("2006-01-02 15:04:05")))
	pdf.Ln(8)
	pdf.Cell(40, 10, fmt.Sprintf("Order No: %s", invoice.OrderSn))
	pdf.Ln(8)
	pdf.Cell(40, 10, fmt.Sprintf("Applicant ID: %d", invoice.UserId))
	pdf.Ln(15)

	// 购买方信息 - 英文
	pdf.SetFont("Arial", "B", 12)
	pdf.Cell(40, 10, "Buyer Information:")
	pdf.Ln(8)
	pdf.SetFont("Arial", "", 12)

	if invoice.ComTitle != "" {
		pdf.Cell(40, 10, fmt.Sprintf("Company: %s", invoice.ComTitle))
		pdf.Ln(8)
	} else if invoice.Title != "" {
		pdf.Cell(40, 10, fmt.Sprintf("Personal: %s", invoice.Title))
		pdf.Ln(8)
	} else {
		pdf.Cell(40, 10, "Title: Not provided")
		pdf.Ln(8)
	}
	pdf.Ln(10)

	// 开票金额信息 - 英文
	pdf.SetFont("Arial", "B", 12)
	pdf.Cell(40, 10, "Amount Information:")
	pdf.Ln(8)
	pdf.SetFont("Arial", "", 12)

	pdf.CellFormat(130, 10, "Total Amount:", "1", 0, "R", false, 0, "")
	pdf.CellFormat(30, 10, fmt.Sprintf("¥%.2f", invoice.Amount), "1", 1, "R", false, 0, "")
	pdf.Ln(5)

	// 税率信息 - 英文
	taxRate := 0.06
	taxAmount := invoice.Amount * taxRate
	totalAmount := invoice.Amount + taxAmount

	pdf.CellFormat(130, 10, fmt.Sprintf("Tax Rate (%.1f%%):", taxRate*100), "1", 0, "R", false, 0, "")
	pdf.CellFormat(30, 10, fmt.Sprintf("¥%.2f", taxAmount), "1", 1, "R", false, 0, "")

	pdf.SetFont("Arial", "B", 12)
	pdf.CellFormat(130, 10, "Total (incl. tax):", "1", 0, "R", false, 0, "")
	pdf.CellFormat(30, 10, fmt.Sprintf("¥%.2f", totalAmount), "1", 1, "R", false, 0, "")
	pdf.Ln(15)

	// 审核状态信息 - 英文
	pdf.SetFont("Arial", "B", 12)
	pdf.Cell(40, 10, "Review Status:")
	pdf.Ln(8)
	pdf.SetFont("Arial", "", 12)

	var statusText string
	switch invoice.Status {
	case 0:
		statusText = "Pending"
		pdf.SetTextColor(255, 165, 0)
	case 1:
		statusText = "Approved"
		pdf.SetTextColor(0, 128, 0)
	case 2:
		statusText = "Rejected"
		pdf.SetTextColor(255, 0, 0)
	default:
		statusText = "Unknown"
		pdf.SetTextColor(128, 128, 128)
	}

	pdf.Cell(40, 10, fmt.Sprintf("Status: %s", statusText))
	pdf.Ln(8)
	pdf.SetTextColor(0, 0, 0)

	// 审核人信息
	if invoice.ReviewerId > 0 {
		pdf.Cell(40, 10, fmt.Sprintf("Reviewer ID: %d", invoice.ReviewerId))
		pdf.Ln(8)
	}

	// 审核时间
	if !invoice.ReviewerTime.IsZero() {
		pdf.Cell(40, 10, fmt.Sprintf("Review Time: %s", invoice.ReviewerTime.Format("2006-01-02 15:04:05")))
		pdf.Ln(8)
	}

	// 审核意见
	if invoice.ReviewerNote != "" {
		pdf.Cell(40, 10, "Review Note:")
		pdf.Ln(8)
		pdf.MultiCell(0, 8, invoice.ReviewerNote, "0", "L", false)
		pdf.Ln(5)
	}

	// 审核公章
	if invoice.ReviewerSeal != "" {
		pdf.Cell(40, 10, "Seal: Stamped")
		pdf.Ln(8)
	}

	pdf.Ln(10)

	// 发票备注信息 - 英文
	pdf.SetFont("Arial", "I", 10)
	pdf.Cell(0, 7, "Remarks:")
	pdf.Ln(5)
	pdf.MultiCell(0, 6, "This is an electronic invoice with the same legal effect as a paper invoice. Please keep it properly.", "0", "L", false)
	pdf.Ln(5)
	pdf.Cell(0, 6, fmt.Sprintf("Generated: %s", time.Now().Format("2006-01-02 15:04:05")))

	// 生成文件名
	timestamp := time.Now().Format("20060102150405")
	filename := fmt.Sprintf("invoice_%s_%d_%s.pdf", invoice.OrderSn, invoice.Id, timestamp)
	filepath := filepath.Join(invoiceDir, filename)

	// 保存文件
	err := pdf.OutputFileAndClose(filepath)
	if err != nil {
		return "", fmt.Errorf("保存PDF文件失败: %v", err)
	}

	return filepath, nil
}

// 简化字体设置函数
func setupChineseFont(pdf *fpdf.Fpdf) string {
	// 直接返回Arial，确保不出现乱码
	pdf.SetFont("Arial", "", 12)
	return "Arial"
}
